import { Component, OnInit, ViewChild } from '@angular/core';
import { NzTreeFlatDataSource, NzTreeFlattener } from 'ng-zorro-antd/tree-view';
import {
  CollectionViewer,
  DataSource,
  SelectionChange,
  SelectionModel,
} from '@angular/cdk/collections';
import { FlatTreeControl, TreeControl } from '@angular/cdk/tree';
import { GroupMember } from 'src/app/domain/group';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { NzMessageService } from 'ng-zorro-antd/message';
import { Observable, of, BehaviorSubject, merge, zip, concat, combineLatest } from 'rxjs';
import { tap, map, switchMap, concatAll, mergeMap } from 'rxjs/operators';
import { Level, OrganizationLevelRelation } from 'src/app/domain/level';
import { LevelService } from 'src/app/service/level.service';
import { LevelSearchComponent } from 'src/app/share/level-search/level-search.component';
import { OrganizationSearchComponent } from 'src/app/share/organization-search/organization-search.component';
import { Organization } from 'src/app/domain/sparrow';
import { EmployeeSearchComponent } from 'src/app/share/employee-search/employee-search.component';
import { RoleSearchComponent } from 'src/app/share/role-search/role-search.component';
import { SysroleSearchComponent } from 'src/app/share/sysrole-search/sysrole-search.component';
import { GroupSearchComponent } from 'src/app/share/group-search/group-search.component';
import { SetModelPermissionComponent } from 'src/app/share/set-model-permission/set-model-permission.component';
import { SetDataPermissionComponent } from 'src/app/share/set-data-permission/set-data-permission.component';
import { EmployeeService, Group, GroupService, JoblevelService, OrganizationService, RoleService, SysroleService } from 'sparrow-permission-lib';
import { FlatNode } from 'src/app/domain/flat-node';
import { DynamicDataSourceForNzTreeService } from 'src/app/service/dynamic-data-source-for-nz-tree.service';
import { NzTreeCommonService } from 'src/app/service/nz-tree-common.service';
import { NzTreeGetChildren } from 'src/app/service/nz-tree-get-children';
import { NzTreeGetLevelChildrenService } from 'src/app/service/nz-tree-get-level-children.service';
import { NzTreeGetGroupChildrenService } from 'src/app/service/nz-tree-get-group-children.service';

@Component({
  selector: 'app-group',
  templateUrl: './group.component.html',
  styleUrls: ['./group.component.css'],
})
export class GroupComponent implements OnInit {
  modelName?: string;
  constructor(
    private fb: FormBuilder,
    private message: NzMessageService,
    private groupService: GroupService,
    private orgService: OrganizationService,
    private employeeService: EmployeeService,
    private roleService: RoleService,
    private levelService: JoblevelService,
    private sysroleService: SysroleService

  ) {}
  dataSource: any;
  hasChild = (_: number, node: FlatNode) => node.expandable;
  treeService: NzTreeCommonService = new NzTreeCommonService();

  ngOnInit(): void {
    let getChildrenService: NzTreeGetChildren =
      new NzTreeGetGroupChildrenService(this.groupService, this.orgService);
    getChildrenService
      .getChildren({
        id: 'root',
        label: 'root',
        level: -1,
        expandable: true,
        type: 'ORG',
      })
      .subscribe(
        (res) => {
          this.dataSource = new DynamicDataSourceForNzTreeService(
            this.treeService.treeControl,
            res,
            getChildrenService
          );
        },
        (error) => {
          this.message.error('初始化失败！' + error);
        }
      );
  }

  // for new organization
  isNewVisible: boolean = false;
  validateForm!: FormGroup;


  submitForm() {
    if (!this.validateForm.valid) {
      // console.log(this.validateForm.)
      for (const i in this.validateForm.controls) {
        if (this.validateForm.controls.hasOwnProperty(i)) {
          this.validateForm.controls[i].markAsDirty();
          this.validateForm.controls[i].updateValueAndValidity();
          console.log(i);
        }
      }
    } else {
      let group: any = this.validateForm.value;

      if(group.id===undefined){
        const organizations$: any[] = this.organizationSearch.selectedParent.map(
          (p) => p.id
        );
        group.isRoot = true;
        this.groupService.create7(group).pipe(
          switchMap((res: any)=>this.groupService.setParentOrgs(res.id, organizations$).pipe(
            map(group=>res)
          ))
        )
        .subscribe((res) => {
          this.ngOnInit()
          this.isNewVisible = false;
        });
      }else{
        let id = group.id
        group.id = undefined
        if(group.name === this.selectedGroup.name){
          group.name = undefined
        }
        if(group.code === this.selectedGroup.code){
          group.code = undefined
        }
        this.groupService.update8(id,group).subscribe()
      }
      this.isNewVisible = false;
    }
  }

  showNew(group: any) {
    console.log(group)
    if(group===undefined){
      this.validateForm = this.fb.group({
        name: [null, [Validators.required]],
        code: [null, [Validators.required]],
      });
    }else{
      this.validateForm = this.fb.group({
        name: [group.name, [Validators.required]],
        code: [group.code, [Validators.required]],
        id: [group.id, [Validators.required]],
      });
    }

    this.isNewVisible = true;
  }

  isReportLineVisible = false;
  showReportLine() {
    this.isReportLineVisible = true;
  }

  isRoleReportTree = false;
  showReportRoleTree() {
    this.isRoleReportTree = true;
  }

  saveReportLine() {
    // let organizationRelation: OrganizationLevelRelation[] = [];
    // this.levelSearch.selectListSelection.selected
    //   .map((p) => p.id)
    //   .forEach((f) => {
    //     organizationRelation.push({
    //       id: { id: this.treeService.selectListSelection.selected[0].id, parentId: f },
    //     });
    //   });
    // this.groupService.saveRelations(organizationRelation).subscribe((res) => {
    //   this.isReportLineVisible = false;
    // });
  }

  delLevels() {
    const groupIds$ =this.treeService.checklistSelection.selected.map(group=>group.id)
    this.groupService.delete7(groupIds$).subscribe()
  }

  selectedGroup: any = {};
  onItemSelect(node: FlatNode): void {
    this.treeService.selectListSelection.toggle(node);

    // get the report line
    const groups$ = this.groupService.getMembers(node.id, 'GROUP').pipe(
      map((res: any) => res.content),
      switchMap((groupRelations) =>
        groupRelations.length === 0
          ? of([])
          : zip(
              ...groupRelations?.map((groupRelation: any) =>
                this.groupService.get7(groupRelation.id.groupId)
              )
            )
      ),
      map((res: any) => Object.assign({}, { groups: res }))
      // map((res: any) => Object.assign(this.selectedGroup, { groups: res }))
    );

    const employees$ = this.groupService.getMembers(node.id, 'EMPLOYEE').pipe(
      map((res: any) => res.content),
      switchMap((groupEmployees) =>
        groupEmployees.length === 0
          ? of([])
          : zip(
              ...groupEmployees?.map((groupEmployee: any) =>
                this.employeeService.get8(groupEmployee.id.employeeId)
              )
            )
      ),
      map((res: any) => Object.assign({}, { employees: res }))
      // map((res: any) => Object.assign(this.selectedGroup, { employees: res }))
    );

    const orgs$ = this.groupService.getMembers(node.id, 'ORGANIZATION').pipe(
      map((res: any) => res.content),
      switchMap((groupOrgs) =>
        groupOrgs.length === 0
          ? of([])
          : zip(
              ...groupOrgs?.map((groupOrg: any) =>
                this.orgService.get4(groupOrg.id.organizationId)
              )
            )
      ),
      map((res: any) => Object.assign({}, { orgs: res }))
      // map((res: any) => Object.assign(this.selectedGroup, { employees: res }))
    );

    const roles$ = this.groupService.getMembers(node.id, 'ROLE').pipe(
      map((res: any) => res.content),
      switchMap((groupRoles) =>
        groupRoles.length === 0
          ? of([])
          : zip(
              ...groupRoles?.map((groupRole: any) =>
                this.roleService.get3(groupRole.id.roleId)
              )
            )
      ),
      map((res: any) => Object.assign({}, { roles: res }))
      // map((res: any) => Object.assign(this.selectedGroup, { employees: res }))
    );

    const levels$ = this.groupService.getMembers(node.id, 'LEVEL').pipe(
      map((res: any) => res.content),
      switchMap((groupLevels) =>
        groupLevels.length === 0
          ? of([])
          : zip(
              ...groupLevels?.map((groupLevel: any) =>
                this.levelService.get6(groupLevel.id.positionLevelId)
              )
            )
      ),
      map((res: any) => Object.assign({}, { levels: res }))
      // map((res: any) => Object.assign(this.selectedGroup, { employees: res }))
    );

    const sysroles$ = this.groupService.getMembers(node.id, 'SYSROLE').pipe(
      map((res: any) => res.content),
      switchMap((groupSysroles) =>
        groupSysroles.length === 0
          ? of([])
          : zip(
              ...groupSysroles?.map((groupSysrole: any) =>
                this.sysroleService.get1(groupSysrole.id.sysroleId)
              )
            )
      ),
      map((res: any) => Object.assign({}, { sysroles: res }))
      // map((res: any) => Object.assign(this.selectedGroup, { employees: res }))
    );


    const group$=this.groupService.get7(node.id)
    const members$ =combineLatest([group$,groups$,employees$, orgs$, roles$, levels$, sysroles$])

    members$.subscribe((res) => {
      this.selectedGroup = Object.assign(this.selectedGroup, ...res)

      // console.log(res)
      // console.log(Object.assign(this.selectedGroup, ...res));
    });
  }

  // add members
  isVisibleForAddEmployee: boolean = false;
  isVisibleForAddGroupRelation: boolean = false;
  isVisibleForAddSysrole: boolean = false;
  // @ViewChild(OrganizationSearchComponent) organizationSearch?: OrganizationSearchComponent;
  // @ViewChild(LevelSearchComponent) levelSearch?: LevelSearchComponent;
  @ViewChild(SysroleSearchComponent) sysroleSearch?: SysroleSearchComponent;
  saveMembers() {
    let groupMember: GroupMember = {
      groupEmployees: [],
      groupOrganizations: [],
      groupRoles: [],
      groupLevels: [],
      groupRelations: [],
      groupSysroles: [],
    };
    this.employeeSearch?.treeService.selectListSelection.selected
      .map((id) => id.me.id)
      .forEach((id) => {
        groupMember.groupEmployees?.push({
          id: {
            groupId:
              this.treeService.selectListSelection.selected[0].id.groupId,
            employeeId: id,
          },
        });
      });

    // this.groupSearch?.treeService.selectListSelection.selected
    //   .map((id) => id.me.id!)
    //   .forEach((id) => {
    //     groupMember.groupRelations?.push({
    //       id: {
    //         parentId:
    //           this.treeService.selectListSelection.selected[0].id.groupId,
    //         groupId: id,
    //       },
    //     });
    //   });

    this.organizationSearch?.selectedParent
      .map((id) => id.me.id!)
      .forEach((id) => {
        groupMember.groupOrganizations?.push({
          id: {
            groupId:
              this.treeService.selectListSelection.selected[0].id.groupId,
            organizationId: id,
          },
        });
      });

    // this.roleSearch?.selectListSelection.selected
    //   .map((id) => id.id!)
    //   .forEach((id) => {
    //     groupMember.groupRoles?.push({
    //       id: {
    //         groupId: this.treeService.selectListSelection.selected[0].id.groupId,
    //         roleId: id,
    //       },
    //     });
    //   });

    // this.levelSearch?.selectListSelection.selected
    //   .map((id) => id.me.id!)
    //   .forEach((id) => {
    //     groupMember.groupLevels?.push({
    //       id: {
    //         groupId: this.treeService.selectListSelection.selected[0].id.groupId,
    //         positionLevelId: id,
    //       },
    //     });
    //   });

    // this.sysroleSearch?.selectListSelection.selected
    // .map((id) => id.me.id!)
    // .forEach((id) => {
    //   groupMember.groupLevels?.push({
    //     id: {
    //       groupId: this.treeService.selectListSelection.selected[0].id.groupId,
    //       positionLevelId: id,
    //     },
    //   });
    // });

    // this.groupService.saveMembers(groupMember).subscribe((res) => {
    //   this.isVisibleForAddEmployee = false;
    //   this.isVisibleForAddOrganization = false;
    //   this.isVisibleForAddRole = false;
    //   this.isVisibleForAddLevel = false;
    //   this.isVisibleForAddGroupRelation = false;
    //   this.isVisibleForAddSysrole = false;
    // });
  }

  @ViewChild(SetModelPermissionComponent)
  setModelPermissionComponent!: SetModelPermissionComponent;
  isVisibleForSetPermission: boolean = false;
  showSetPermissionModal() {
    this.isVisibleForSetPermission = true;
    setTimeout(() => {
      this.setModelPermissionComponent.models.push({
        name: this.modelName!,
        nameTxt: '菜单',
      });
    });
  }

  saveModelPermission() {
    this.setModelPermissionComponent.addPermission();
    this.isVisibleForSetPermission = false;
  }

  // data permission
  isVisibleForSetDataPermission: boolean = false;
  @ViewChild(SetDataPermissionComponent)
  setDataPermissionComponent!: SetDataPermissionComponent;
  showSetDataPermissionModal() {
    this.isVisibleForSetDataPermission = true;
    setTimeout(() => {
      const dataIds$: any[] = this.treeService.selectListSelection.selected.map(
        (sel) => sel.me.id
      );
      this.setDataPermissionComponent.dataIds = [];
      this.setDataPermissionComponent.dataIds.push(...dataIds$);
      this.setDataPermissionComponent.models.push({
        name: this.modelName!,
        nameTxt: '菜单',
      });
    });
  }

  saveDataPermission() {
    this.setDataPermissionComponent.addPermission();
    this.isVisibleForSetDataPermission = false;
  }

  handleCancel() {
    this.isNewVisible = false;
    this.isReportLineVisible = false;
    this.isRoleReportTree = false;
    this.isVisibleForSetPermission = false;
    this.isVisibleForSetDataPermission = false;
  }

  showGroupEditForm(group: any){
    this.isNewVisible = true
  }

  isVisibleForAddOrganization: boolean = false;
  @ViewChild(OrganizationSearchComponent)
  organizationSearch!: OrganizationSearchComponent;
  saveOrgs(){
    const orgIds$= this.organizationSearch?.selectedParent?.map(org=>org.id) as Array<any>
    this.groupService.addMembers(this.selectedGroup.id,'ORGANIZATION', orgIds$).subscribe(
      res=>this.isVisibleForAddOrganization = false
    )
  }

  @ViewChild(EmployeeSearchComponent) employeeSearch?: EmployeeSearchComponent;
  saveEmployees(){
    const employeeIds$= this.employeeSearch?.selectedUser?.map(employee=>employee.id) as Array<any>
    this.groupService.addMembers(this.selectedGroup.id,'EMPLOYEE', employeeIds$).subscribe(
      res=>this.isVisibleForAddEmployee = false
    )
  }

  isVisibleForAddGroup: boolean =false
  showAddGroup(group: any){
    this.isVisibleForAddGroup = true
  }

  @ViewChild(GroupSearchComponent) groupSearch?: GroupSearchComponent;
  saveGroups(){
    const groupIds$= this.groupSearch?.selectedUser?.map(group=>group.id) as Array<any>
    this.groupService.addMembers(this.selectedGroup.id,'GROUP', groupIds$).subscribe(
      res=>this.isVisibleForAddGroup = false
    )
  }

  isVisibleForAddRole: boolean =false
  @ViewChild(RoleSearchComponent) roleSearch!: RoleSearchComponent;
  saveRoles(){
    const roleIds$= this.roleSearch.selectedRoles.map(role=>role.id) as Array<any>
    this.groupService.addMembers(this.selectedGroup.id,'ROLE', roleIds$).subscribe(
      res=>this.isVisibleForAddRole = false
    )
  }

  isVisibleForAddLevel: boolean = false;
  @ViewChild(LevelSearchComponent) levelSearch!: LevelSearchComponent;
  saveLevels(){
    const levelIds$= this.levelSearch.selectedLevels.map(level=>level.id) as Array<any>
    this.groupService.addMembers(this.selectedGroup.id,'LEVEL', levelIds$).subscribe(
      res=>this.isVisibleForAddLevel = false
    )
  }

  onEmployeeRemove(id: any){
    this.groupService.removeMembers(this.selectedGroup.id,'EMPLOYEE',[id]).subscribe()
  }

  onGroupRemove(id: any){
    this.groupService.removeMembers(this.selectedGroup.id,'GROUP',[id]).subscribe()

  }
  onOrgRemove(id: any){
    this.groupService.removeMembers(this.selectedGroup.id,'ORGANIZATION',[id]).subscribe()

  }
  onRoleRemove(id: any){
    this.groupService.removeMembers(this.selectedGroup.id,'ROLE',[id]).subscribe()

  }
  onLevelRemove(id: any){
    this.groupService.removeMembers(this.selectedGroup.id,'LEVEL',[id]).subscribe()

  }

}
